package com.code2roc.fastboot.system.setting.bizlogic;

import com.code2roc.fastboot.framework.cache.CacheUtil;
import com.code2roc.fastboot.framework.extra.datadic.CodeItem;
import com.code2roc.fastboot.system.cache.DataBaseDicCacheInfo;
import com.code2roc.fastboot.system.setting.model.SystemCodeItemDO;
import com.code2roc.fastboot.system.setting.model.SystemCodeMainDO;
import com.code2roc.fastboot.system.setting.service.ISystemCodeItemService;
import com.code2roc.fastboot.system.setting.service.ISystemCodeMainService;
import com.code2roc.fastboot.model.BaseBootLogic;
import com.code2roc.fastboot.util.BootUtil;
import com.code2roc.fastboot.framework.util.CommonUtil;
import com.code2roc.fastboot.framework.util.FileUtil;
import com.code2roc.fastboot.framework.util.LogUtil;
import com.code2roc.fastboot.framework.util.StringUtil;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

@Component
public class DataDicLogic extends BaseBootLogic {
    @Autowired
    private ISystemCodeMainService codeMainService;
    @Autowired
    private ISystemCodeItemService codeItemService;
    @Autowired
    private CacheUtil cacheUtil;

    public void insert(SystemCodeMainDO entity){
        codeMainService.insert(entity);
        cacheUtil.refreshCache("DataBaseDic",entity.getCode_name());
    }

    public void delete(String row_id){
        SystemCodeMainDO entity = codeMainService.selectOne(row_id);
        codeMainService.delete(row_id);
        cacheUtil.deleteCache("DataBaseDic",entity.getCode_name());
    }

    public void update(SystemCodeMainDO entity){
        codeMainService.update(entity);
        cacheUtil.refreshCache("DataBaseDic",entity.getCode_name());
    }

    public SystemCodeMainDO detail(String row_id){
        return codeMainService.selectOne(row_id);
    }

    public void refresh(String row_id){
        SystemCodeMainDO entity = codeMainService.selectOne(row_id);
        cacheUtil.deleteCache("DataBaseDic",entity.getCode_name());
    }

    public boolean exit(String codeName){
        return cacheUtil.existCache("DataBaseDic",codeName);
    }

    public List<CodeItem> getCodeItemList(String codeName){
        DataBaseDicCacheInfo dataBaseDicCacheInfo = (DataBaseDicCacheInfo)cacheUtil.getCache("DataBaseDic",codeName);
        return dataBaseDicCacheInfo.getCodeItemList();
    }

    public String exportData(List<String> codeIDList) {
        String fileid = "";
        try {
            DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            Calendar calendar = Calendar.getInstance();
            String dateName = df.format(calendar.getTime());
            fileid = "DataDicExport_" + dateName + CommonUtil.getNewGuid();
            String filename = fileid + ".xml";
            String filefullpath = "tempfiles/export/" + filename;
            FileUtil.initfloderPath("tempfiles/export/");
            Document doc = DocumentHelper.createDocument();
            Element root = doc.addElement("settingfile");
            Element filetype = root.addElement("filetype");
            filetype.setText("datadic");

            Element codemainlist = root.addElement("codemainlist");
            for (String codeID : codeIDList) {
                SystemCodeMainDO codeMainDO = detail(codeID);
                Element codemain = codemainlist.addElement("codemain");
                for (Field field : codeMainDO.getClass().getDeclaredFields()) {
                    if (!Modifier.isStatic(field.getModifiers())) {
                        field.setAccessible(true);
                        Element tablefield = codemain.addElement(field.getName());
                        tablefield.setText(String.valueOf(field.get(codeMainDO)));
                    }
                }
            }

            Element codeitemlist = root.addElement("codeitemlist");
            List<SystemCodeItemDO> codeItemDOList = codeItemService.selectRangeListByField("code_id",codeIDList);
            for (SystemCodeItemDO codeItemDO:codeItemDOList) {
                Element codeitem = codeitemlist.addElement("codeitem");
                for (Field field : codeItemDO.getClass().getDeclaredFields()) {
                    if (!Modifier.isStatic(field.getModifiers())) {
                        field.setAccessible(true);
                        Element tablefield = codeitem.addElement(field.getName());
                        tablefield.setText(String.valueOf(field.get(codeItemDO)));
                    }
                }
            }

            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");
            FileOutputStream out;
            out = new FileOutputStream(filefullpath);
            XMLWriter writer = new XMLWriter(out, format);
            writer.write(doc);
            writer.close();

            StringBuilder builder = new StringBuilder();
            builder.append("导出字典信息成功！" + CommonUtil.getNewLine());
            LogUtil.writeLog("setting/datadic", "log", builder.toString());
        } catch (Exception e) {
            e.printStackTrace();
            StringBuilder builder = new StringBuilder();
            builder.append("导出字典信息失败！" + CommonUtil.getNewLine());
            builder.append("失败异常信息:" + CommonUtil.getNewLine());
            builder.append(e.getMessage() + CommonUtil.getNewLine());
            builder.append("失败堆栈信息:" + CommonUtil.getNewLine());
            builder.append(e.getStackTrace());
            LogUtil.writeLog("setting/datadic", "log", builder.toString());
        }finally {
            cacheUtil.refreshCache("DataBaseDic");
        }
        return fileid;
    }


    @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.READ_UNCOMMITTED)
    public String importData(InputStream stream) {
        String errormsg = "";
        Exception exception = null;
        try {
            //解析xml
            SAXReader reader = new SAXReader();
            Document document = reader.read(stream);
            Element root = document.getRootElement();
            Element filetype = root.element("filetype");
            if (filetype != null && filetype.getText().equals("datadic")) {
                List<Element> codemainlist = root.element("codemainlist").elements("codemain");
                for (Element codemain : codemainlist) {
                    SystemCodeMainDO codeMainDO = new SystemCodeMainDO();
                    for (Field field : codeMainDO.getClass().getDeclaredFields()) {
                        if (!Modifier.isStatic(field.getModifiers())) {
                            field.setAccessible(true);
                            Element filednode = codemain.element(field.getName());
                            field.set(codeMainDO, BootUtil.convetXmlContent2FieldContent(filednode.getText(), field.getType()));
                        }
                    }
                    SystemCodeMainDO dbinfo = codeMainService.selectOne(codeMainDO.getRow_id());
                    if (dbinfo == null) {
                        insert(codeMainDO);
                    } else {
                        update(codeMainDO);
                    }
                    codeItemService.deleteByField("code_id",codeMainDO.getRow_id());
                }


                List<Element> codeitemlist = root.element("codeitemlist").elements("codeitem");
                for (Element codeitem : codeitemlist) {
                    SystemCodeItemDO codeItemDO = new SystemCodeItemDO();
                    for (Field field : codeItemDO.getClass().getDeclaredFields()) {
                        if (!Modifier.isStatic(field.getModifiers())) {
                            field.setAccessible(true);
                            Element filednode = codeitem.element(field.getName());
                            field.set(codeItemDO, BootUtil.convetXmlContent2FieldContent(filednode.getText(), field.getType()));
                        }
                    }
                    codeItemService.insert(codeItemDO);
                }
            } else {
                errormsg = "导入文件不是字典文件！";
            }
        } catch (Exception e) {
            exception = e;
            errormsg = "导入失败";
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
        } finally {
            StringBuilder builder = new StringBuilder();
            if (StringUtil.isEmpty(errormsg)) {
                builder.append("导入字典成功！" + CommonUtil.getNewLine());
            } else {
                builder.append("导入字典失败！" + CommonUtil.getNewLine());
            }
            if (!StringUtil.isEmpty(errormsg)) {
                if (errormsg.equals("导入失败")) {
                    builder.append("失败异常信息:" + CommonUtil.getNewLine());
                    builder.append(exception.getMessage() + CommonUtil.getNewLine());
                    builder.append("失败堆栈信息:" + CommonUtil.getNewLine());
                    builder.append(exception.getStackTrace());
                } else {
                    builder.append("导入失败信息:" + errormsg + CommonUtil.getNewLine());
                }
            }
            LogUtil.writeLog("setting/datadic", "log", builder.toString());
        }
        return errormsg;
    }

}
